
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <string.h>

#include <auxiliares.h>
#include <parser.h>
#include <calibracion.h>
#include <camponormal.h>
#include <tripla.h>
#include <matriz.h>
#include <sistema.h>
#include <paths.h>
#include <list>
#include <matriz_esp.h>

using namespace std;

/** VARIABLES GLOBALES **/

unsigned int filas_imagen = 0;          // De la imagen recortada
unsigned int colum_imagen = 0;

string num_imagenes[3] = {"0", "4", "11"};
string tipo_imagen = "esfera";

/* Arreglo con las direcciones de iluminacion, una para cada imagen */

tripla_dbl vectores_S_reales[] =
{
        tripla_dbl(-0.480808,            0.403259,              0.778592),
        tripla_dbl(-0.163712,            0.0982272,             0.981606),
        tripla_dbl(-0.180077,           -0.0654826,     		0.98147),
        tripla_dbl(-0.431998,           -0.127999,              0.892745),
        tripla_dbl(-0.485085,           -0.328606,              0.810377),
        tripla_dbl(-0.53593,            -0.110339,              0.837021),
        tripla_dbl(-0.41439,             0.239071,              0.878138),
        tripla_dbl(-0.417497,            0.0642302,             0.906406),
        tripla_dbl(-0.339438,            0.12931,               0.931698),
        tripla_dbl(-0.340151,            0.0323953,             0.939813),
        tripla_dbl(-0.0492659,           0.0985318,     		0.993914),
        tripla_dbl(-0.354617,           -0.16119,               0.921013)
       
        /*
        tripla_dbl( 0.403259,           0.480808,               0.778592),
        tripla_dbl( 0.0982272,          0.163712,               0.981606),
        tripla_dbl(-0.0654826,          0.180077,               0.98147),
        tripla_dbl(-0.127999,           0.431998,               0.892745),
        tripla_dbl(-0.328606,           0.485085,               0.810377),
        tripla_dbl(-0.110339,           0.53593,                0.837021),
        tripla_dbl( 0.239071,           0.41439,                0.878138),
        tripla_dbl( 0.0642302,          0.417497,               0.906406),
        tripla_dbl( 0.12931,            0.339438,               0.931698),
        tripla_dbl( 0.0323953,          0.340151,               0.939813),
        tripla_dbl( 0.0985318,          0.0492659,              0.993914),
        tripla_dbl(-0.16119,            0.354617,               0.921013)
        */
};

tripla_dbl vectores_S[] =
{
        tripla_dbl(0, 0, 0),
        tripla_dbl(0, 0, 0),
        tripla_dbl(0, 0, 0)
};

bool usar_S_orig = false;                       // Para saber que vectores S usar
bool mostrar_recortes = false;          // Para generar la imagen recortada
bool mostrar_debug = false;

/* Esta matriz contendra la matriz de la ecuacion 5 */

matriz<tripla_dbl>* campo_normal_M;


bool leerParametros(int argc, char** argv);

int main(int argc, char** argv)
{
        /* Leo los parametros de entrada */
       
        if(!leerParametros(argc, argv)) return 1;
       
        if(mostrar_debug)
        {
                cout << "Las imagenes a utilizar son... " << endl << endl;
                cout << " - " << path_imagen(tipo_imagen, num_imagenes[0]) << endl;
                cout << " - " << path_imagen(tipo_imagen, num_imagenes[1]) << endl;
                cout << " - " << path_imagen(tipo_imagen, num_imagenes[2]) << endl << endl;
               
                cout << "Las esferas a utilizar son... " << endl << endl;
                cout << " - " << path_esfera(num_imagenes[0]) << endl;
                cout << " - " << path_esfera(num_imagenes[1]) << endl;
                cout << " - " << path_esfera(num_imagenes[2]) << endl << endl;
        }      
                       
        /* Cargamos los archivos */    

        if(!obtenerDirecciones())
        {
                cout << "ERROR: El programa no puede continuar..." << endl;
                return 1;
        }
       
        /* Obtenemos las dimensiones de la matriz */
       
        parsearMascaraImagen();
       
        /* Matrices con las intensidades de las imagenes a procesar */
 
        matriz<uint8_t> imagen_1(filas_imagen, colum_imagen);
        matriz<uint8_t> imagen_2(filas_imagen, colum_imagen);
        matriz<uint8_t> imagen_3(filas_imagen, colum_imagen);
       
        if(!parsearImagenes(imagen_1, imagen_2, imagen_3))
        {
                cout << "ERROR: El programa no puede continuar..." << endl;
                return 1;
        }
       
        obtener_campo_normal(imagen_1, imagen_2, imagen_3);             // Esta funcion hace new de campo_normal_M
             
        matriz_esp M(*campo_normal_M);          // Armamos la matriz esparsa. Al hacerlo se calcula Mt*M y Mt*b
              
        delete(campo_normal_M);                 // Liberamos algo de memoria
               
        vector<double> res = M.resolver();     
             
        // Redirigimos a un archivo las soluciones validas
       
        // Ahora me quedo solo con las soluciones validas
       
        ofstream archivo;
        archivo.open("Zs.txt");
       
        int indice = 0;
       
        for(unsigned int i = 0; i < filas_imagen; i++)
        {
                for(unsigned int j = 0; j < colum_imagen; j++)
                        archivo << res[indice++] << endl;
               
                indice++;       // Salteamos la variable con basura
        }
       
        archivo.close();
                       
        return 0;
}

bool leerParametros(int argc, char** argv)
{
        for(int i = 1; i < argc; i++)
        {
                if(!strncmp("-i", argv[i], 3))
                {
                        // Tengo que agarrar el tipo de imagenes y los 3 numeros
                       
                        tipo_imagen = argv[++i];
                       
                        num_imagenes[0] = argv[++i];
                        num_imagenes[1] = argv[++i];
                        num_imagenes[2] = argv[++i];
                                                                       
                        continue;                      
                }
               
                if(!strncmp("-s", argv[i], 3))
                {
                        usar_S_orig = true;
                        continue;
                }
               
                if(!strncmp("-o", argv[i], 3))
                {
                        mostrar_recortes = true;
                        continue;
                }
               
                if(!strncmp("-d", argv[i], 3))
                {
                        mostrar_debug = true;
                        continue;
                }
               
                cout << argv[i] << ": Opcion no reconocida!" << endl;          
        }
       
        return true;
}
 


